// SPDX-License-Identifier: GPL-2.0
/*
 * GUP: FAST
 *
 * (C) 2024.01.09 <buddy.zhang@aliyun.com>
 */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/pagemap.h>

#define DEV_NAME		"BiscuitOS-GUP"
#define BISCUITOS_IO		0xBD
#define MM_GUP			_IO(BISCUITOS_IO, 0x00)

static long BiscuitOS_ioctl(struct file *filp,
                        unsigned int ioctl, unsigned long arg)
{
	struct page *page;
	void *mem;

	switch (ioctl) {
	case MM_GUP:
		/* GUP */
		get_user_pages_fast(arg, 1, FOLL_WRITE, &page);

		/* TEMP MAPPING */
		mem = kmap(page);
		sprintf((char *)mem, "Hello BiscuitOS");
		kunmap(page);
		break;
	}
	return 0;
}

static struct file_operations BiscuitOS_fops = {
	.owner		= THIS_MODULE,
	.unlocked_ioctl	= BiscuitOS_ioctl,
};

static struct miscdevice BiscuitOS_drv = {
	.minor	= MISC_DYNAMIC_MINOR,
	.name	= DEV_NAME,
	.fops	= &BiscuitOS_fops,
};

static int __init BiscuitOS_init(void)
{
	misc_register(&BiscuitOS_drv);
	return 0;
}

static void __exit BiscuitOS_exit(void)
{
	misc_deregister(&BiscuitOS_drv);
}

module_init(BiscuitOS_init);
module_exit(BiscuitOS_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("BiscuitOS <buddy.zhang@aliyun.com>");
MODULE_DESCRIPTION("BiscuitOS MMU");
